package main.java.LeetCode.ClassicalAlgorithm.RateLimit.Impl;

import main.java.LeetCode.ClassicalAlgorithm.RateLimit.RateLimit;

import java.util.LinkedList;

public class SlideWindow implements RateLimit {

    private final int windowSize;
    private final int threshold;
    private final LinkedList<TimeStamp> window;
    private long rate;
    private long beginTime;
    private final int duration;


    private static class TimeStamp{
        long index;
        long count;

        private TimeStamp(long index,long count){
            this.index = index;
            this.count = count;
        }

        private TimeStamp(){}
    }

    public SlideWindow(int granularity,int threshold){
        this.windowSize = granularity;
        this.window = new LinkedList<>();
        this.threshold = threshold;
        this.rate = 0;
        this.beginTime = System.currentTimeMillis();
        this.duration = 1000/windowSize;
    }



    @Override
    public synchronized boolean isLimit(long count) {

        long nowIndex = getIndex();

        if(window.isEmpty()||nowIndex-window.getLast().index>=windowSize){
            window.clear();
            this.beginTime = System.currentTimeMillis();
            window.addLast(new TimeStamp(getIndex(),count));
            rate = count;
            return rate>=threshold;
        }


        while (nowIndex-window.getFirst().index>=windowSize){
            TimeStamp timeStamp = window.removeFirst();
            rate = rate-timeStamp.count;
        }

        rate = rate+count;

        if(window.getLast().index==nowIndex) window.getLast().count += count;
        else window.addLast(new TimeStamp(nowIndex,count));

        return rate>=threshold;
    }

    private long getIndex(){
        long now = System.currentTimeMillis();
        return (now-beginTime)/duration;
    }




}
